home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / ameshC / ameshC.c next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  23.2 KB  |  995 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * Copyright (C) 1991, Silicon Graphics, Inc.
  19.  * All Rights Reserved.
  20.  */
  21. /*  Standard Disclaimer ...
  22. This source code provided as is with no warranty as to 
  23. suitability for any purpose .... enjoy                     */
  24.  
  25. /* Amesh.c  Real-Time FFT visualization of an audio stream
  26.  
  27. Credits:
  28. Original Concept and implementation
  29.     David S. Maynard
  30. FFT code
  31.     Bruce Karsh
  32. Wheel View concept and implementation
  33.     Chris Perry
  34. Track Ball emulation code by
  35.     Thant Tessman
  36.  
  37. I hope you enjoy this program.
  38.  
  39. Please let me know if you make any cool additions
  40.     David S. Maynard
  41.     Silicon Graphics Computer Systems
  42.     dsm@sgi.com
  43.     February 25, 1992
  44. */
  45.  
  46. #include <stdio.h>
  47. #include <gl.h>
  48. #include <device.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <math.h>
  52. #include <sys/types.h>
  53. #include <sys/dir.h>
  54. #include <string.h>
  55.  
  56. #include <audio.h>
  57.  
  58. /* ORDER defines the number of frequency bands plotted */
  59. /* ORDER is the number of points along the x-axis   */
  60. #define ORDER 64
  61.  
  62. /* DURATION is the number of power spectrums plpotted  */
  63. /* DURATION is the number of points along the y-axis  */
  64. #define DURATION 25
  65.  
  66. /* BUFCHUNKSIZE is the default number of samples transformed per frame */
  67. /* BUFCHUNKSIZE must be at least twice ORDER to avoid aliasing in the */
  68. /* frequncy domain */
  69. #define BUFCHUNKSIZE 128
  70. int curfftsize = BUFCHUNKSIZE;
  71.  
  72. /* Basic program loop is as follows
  73.     while (true)
  74.     {
  75.     read all waiting audio samples from input buffer
  76.     perform an FFT on the last "curfftsize" samples
  77.     calculate the power in each of the lowest "ORDER" frequency bands
  78.     add this power spectrum to the front of the rolling carpet
  79.     plot the rolling carpet of power spectrums
  80.     }
  81. */
  82.  
  83. #define RGBTIMEFACT 3.2
  84. #define LMTIMEFACT 1.35
  85. #define MMTIMEFACT 1.35
  86.  
  87. #define MAXBUFFERSIZE 60000
  88. #define ABUFFERSIZE 40000
  89. float v0[3] = { -1.0, -1.0, -1.0 } ;
  90. float v1[3] = { -1.0, -1.0,  1.0 } ;
  91. float v2[3] = { -1.0,  1.0,  1.0 } ;
  92. float v3[3] = { -1.0,  1.0, -1.0 } ;
  93. float v4[3] = {  1.0, -1.0, -1.0 } ;
  94. float v5[3] = {  1.0, -1.0,  1.0 } ;
  95. float v6[3] = {  1.0,  1.0,  1.0 } ;
  96. float v7[3] = {  1.0,  1.0, -1.0 } ;
  97.  
  98. #define MAXDURATION (DURATION<<1)
  99. #define TWOPI  6.2832
  100. float amp[MAXDURATION][ORDER];       /* independent variable */
  101.  
  102. float power[DURATION][ORDER];   /* vertices of rolling carpet */
  103. float ident_matrix[4][4] = {
  104.     {1.0, 0.0, 0.0, 0.0},
  105.     {0.0, 1.0, 0.0, 0.0},
  106.     {0.0, 0.0, 1.0, 0.0},
  107.     {0.0, 0.0, 0.0, 1.0},
  108. };
  109. float xlogpos[ORDER];     /* table to store pre-computed x coordinates log scale */
  110.  
  111.  
  112. char    *myname;
  113. ALport port;
  114. ALconfig conf;
  115. int curlinewidth = 2;
  116. int candoRGB = 0;
  117. int mono = 0;
  118. int DB = 1;   /* if true use double buffering */
  119. int framecount =0;
  120. int zbuf = 0;  /* if true use zbuffering */
  121.  
  122.  /* use 16 bit audio samples ( no cheesy 8 bit mu-law please) */
  123.  
  124. typedef short SAMPLE; 
  125.  
  126.  
  127.  
  128. SAMPLE tbuf[2*MAXBUFFERSIZE];
  129.  
  130. extern float spectrum( SAMPLE * , int , float *, int, float );
  131.  
  132.  
  133. float dist=0.0, d_dist=0.0;
  134. Angle azim=0, inc=700, twist=0;
  135. Angle d_azim=0, d_inc=0;
  136.  
  137. short mx, my, omx, omy, nmx, nmy;
  138. long origx, origy, sizex, sizey;
  139.  
  140. int y;
  141. long mode, playmode, prevmode;
  142. int active=TRUE;
  143. long gid;
  144. #define    TIMELINES    1
  145. #define    FREQLINES    2
  146. #define    AMPLINES    4
  147.  
  148. int low_res, low_tmp;
  149.  
  150. int function = 0;
  151. #define REORIENT 1
  152. #define REDISTANCE 2
  153. #define PREPAREAIFF 3
  154.  
  155. #define DTHETA 0.6
  156. #define PWRMAX 100.0
  157.  
  158. int idur=0;
  159. float maxpwr = PWRMAX;  /* maxpwr used for automatic gain control */
  160. float pwr = 1.0;
  161. int facing = 0, facingz = 0, buggy = 0, buggyview = 0;
  162.  
  163. float p1[ 3], p2[ 3], tv1[ 3], tv2[ 3];
  164. int dotmesh;
  165.  
  166. short    mute;        /* if TRUE then don't play sound out */
  167. short logfreq = 0;        /* IF TRUE USE LOG SCALE FOR FREQUENCY AXIS */
  168. short tmeshmode = 0;    /* IF TRUE USE Tmesh drawing mode */
  169. #define    FIRSTTIME    1
  170. #define    INPORT        2
  171. #define    OUTPORT        4
  172.  
  173.  
  174. /* pop-up menu id's */
  175. long    mainmenu, linemenu, samplemenu, wheelmenu, drawmenu, fftmenu;
  176.  
  177. /* typedef         void (* ALerrfunc) (long, const char*, ...); /*XXXX*/
  178.  
  179. static void drawpower();
  180. static void mappower();
  181. static void drawaxis();
  182.  
  183.  
  184. static void    generate(void)
  185. {
  186.     int id, io;
  187.     for (id=0;id<MAXDURATION;id++)
  188.         for (io=0;io<ORDER;io++)
  189.             amp[id][io] =  0.0;
  190. }
  191.  
  192. static void    place(void)
  193. {
  194.     int    nxt = idur, id, io;
  195.  
  196.     for (id=0;id<DURATION;id++) {
  197.         for (io=0;io<ORDER;io++) {
  198.             power[id][io] = amp[nxt][io];            /* y */
  199.         }
  200.         nxt--;
  201.         if (nxt < 0 ) nxt = MAXDURATION-1;
  202.     }
  203. }
  204.  
  205.  
  206. static void    drawbuggy()
  207. {
  208.     
  209.     float gravity = -0.01;
  210.     float bikelength = 3;
  211.     float t1ypos, t2ypos, t1yprev, t2yprev;
  212.  
  213.     static float thetaa = 0.0;
  214.  
  215.     p1 [0] = ORDER/2 + facing;
  216.     if (logfreq) p1[0] = xlogpos[ORDER/2 + facing] ;
  217.     p1 [2] = -DURATION/2 + facingz;
  218.     p2 [0] = ORDER/2 + facing;
  219.     if (logfreq) p2[0] = xlogpos[ ORDER/2 + facing] ;
  220.     p2 [2] = -DURATION/2 +facingz - bikelength;
  221.  
  222.     t1ypos = power[ -(int)p1[2]][ORDER/2 + facing]/maxpwr;
  223.     t2ypos = power[ -(int)p2[2]][ORDER/2 + facing]/maxpwr;
  224.  
  225.     t1yprev = power[ -(int)p1[2]-1][ORDER/2 + facing]/maxpwr;
  226.     t2yprev = power[ -(int)p2[2]-1][ORDER/2 + facing]/maxpwr;
  227.  
  228.     tv1 [1] += ( p1[ 1] > t1ypos) ? gravity : t1ypos - t1yprev;
  229.     tv2 [1] += ( p2[ 1] > t2ypos) ? gravity : t2ypos - t2yprev;
  230.  
  231.     p1[ 1] += tv1[ 1];
  232.     p2[ 1] += tv2[ 1];
  233.  
  234.     if ( p1[ 1] < 0.0) {
  235.         p1[ 1] = 0.0;
  236.         tv1[ 1] *= - 0.2;
  237.         }
  238.     if ( p2[ 1] < 0.0) {
  239.         p2[ 1] = 0.0;
  240.         tv2[ 1] *= -0.2;
  241.         }
  242.  
  243.   if ( buggy && !buggyview) {
  244.     pushmatrix();
  245.     scale(1.0, 1.0/20.0, (float)DURATION/(float)ORDER);
  246.     rotate(900, 'y');
  247.     pushmatrix();
  248.     translate((-p1[2] + 1) * ((float)ORDER/(float)DURATION),
  249.         1 + p1[1]*20.0, p1[0]-0.05);
  250.  
  251.     RGBcolor(0xff,0xff,0xff);
  252.     circi( 0, 0, 1);
  253.     translate( 0, 0, 0.1);
  254.     circi( 0, 0, 1);
  255.     popmatrix();
  256.     
  257.     if ( p1[ 1] > 0.5) thetaa+= DTHETA/2.0;
  258.     else thetaa += DTHETA;
  259.     if ( thetaa > TWOPI) thetaa-=TWOPI;
  260.  
  261.     RGBcolor(0xff,0,0);
  262.     move((-p1[2] + 1) * ((float)ORDER/(float)DURATION) + 0.9 *
  263.         sinf(thetaa), p1[1]*20.0 + 1 - 0.9 * cosf(thetaa), p1[0]);
  264.     draw((-p1[2] + 1) * ((float)ORDER/(float)DURATION) - 0.9 *
  265.         sinf(thetaa), p1[1]*20.0 + 1 + 0.9 * cosf(thetaa), p1[0]);
  266.     move((-p1[2] + 1)  * ((float)ORDER/(float)DURATION) - 0.9 *
  267.         sinf(thetaa + TWOPI/4.0), p1[1]*20.0 + 1 + 0.9 *
  268.         cosf(thetaa + TWOPI/4.0), p1[0]);
  269.     draw((-p1[2] + 1)  * ((float)ORDER/(float)DURATION) + 0.9 *
  270.         sinf(thetaa + TWOPI/4.0), p1[1]*20.0 + 1 - 0.9 * 
  271.         cosf(thetaa + TWOPI/4.0), p1[0]);
  272.  
  273.     popmatrix();
  274.     }
  275. }    
  276.  
  277. static void    draw_scene(void) 
  278. {
  279.     RGBcolor(00,00,00);
  280.     clear();
  281.     if (zbuf) zclear();
  282.     pushmatrix();
  283.     if (buggyview) lookat (p1[ 0] - ORDER/2, ORDER/DURATION * (- p1[ 2] - 14),
  284.         20.0*p1[ 1] + 2, p1[ 0] - ORDER/2,
  285.         ORDER/DURATION * (- p1[ 2] - 14) - DURATION,
  286.         (20.0*p1[ 1] + 2) / 4.0, 1800);
  287.     else polarview(dist+d_dist, azim+d_azim, inc+d_inc, twist);
  288.     rotate(900, 'x');
  289.     translate(-ORDER/2.0, 0.0, ORDER/2.0);
  290.     scale(1.0,20.0, ORDER/DURATION);
  291.  
  292.     place();
  293.     drawpower();
  294.  
  295.     if ( buggy || buggyview) drawbuggy();
  296.     popmatrix();
  297.  
  298.     if (DB) swapbuffers(); else gsync();
  299. }
  300.  
  301.  
  302. static void    drawpower() 
  303. {
  304.     float    dx,dz,xp,zp,vert[3];
  305.     float  invmax, thresh;
  306.     float *p;
  307.     int    ORD2 = ORDER >> 1,
  308.     bright,
  309.     id,io,
  310.     rc,gc,bc;
  311.  
  312.     dx = 1.0;
  313.     invmax = 1.0/maxpwr;
  314.     thresh = maxpwr/50.0;
  315.     framecount++;
  316.     linewidth(curlinewidth);
  317.     if (mono) {
  318.     rc = 0x80;
  319.     gc = 0x80;
  320.     bc = 0x80;
  321.     cpack(0xffffff);
  322.     }
  323.     if (tmeshmode) {
  324.     dz = 1.0;
  325.     zp = -DURATION+dz;
  326.     cpack(0xffffff);
  327.     if (!buggyview) /* Draw tmesh back to front */
  328.           for(id=DURATION-1;id>=1; id--) {
  329.         xp = -1.0;
  330.         p = &power[id][0];
  331.         bgntmesh();
  332.         for (io=0;io<ORDER;io++,p++) {
  333.         if (!mono) {
  334.             if (io <= ORD2)
  335.             {
  336.             rc =  0xff*(ORD2-io)/ORDER;
  337.             gc = 0xff*(io)/ORDER;
  338.             bc = 0;}
  339.             else
  340.             {
  341.             rc = 0;
  342.             gc = 0xff*(ORDER-io)/ORDER;
  343.             bc = (0x80*io)/ORDER;
  344.             }
  345.  
  346.         if ( *p > thresh)
  347.             {
  348.             bright = (int)(0x5f* ((*p))*invmax) + 0x10;    
  349.             cpack ( (rc+bright&0xff) |
  350.             (((gc+bright)<<8)&0xff00) |
  351.             (((bc+bright) << 16)&0xff0000));
  352.             }
  353.         else cpack(0x222222);
  354.         }
  355.         if( logfreq) xp = xlogpos[io]; else xp += dx;
  356.         vert[0] = xp; vert[1] = *p*invmax; vert[2] = zp;
  357.         v3f(vert);
  358.         vert[0] = xp; vert[1] = power[id-1][io]*invmax; vert[2] = zp+dz;
  359.         v3f(vert);
  360.         }
  361.         endtmesh();
  362.         zp += dz;
  363.       }
  364.        else  /* buggyview, draw from front to back: we are facing the front */
  365.           {
  366.       dz = -1.0;
  367.       zp = 0;
  368.       for(id=0 ;id<=DURATION-1; id++) {
  369.         xp = -1.0;
  370.         p = &power[id][0];
  371.         bgntmesh();
  372.         for (io=0;io<ORDER;io++,p++) {
  373.         if (!mono) {
  374.             if (io <= ORD2)
  375.             {
  376.             rc =  0xff*(ORD2-io)/ORDER;
  377.             gc = 0xff*(io)/ORDER;
  378.             bc = 0;}
  379.             else
  380.             {
  381.             rc = 0;
  382.             gc = 0xff*(ORDER-io)/ORDER;
  383.             bc = (0x80*io)/ORDER;
  384.             }
  385.  
  386.         if ( *p > thresh)
  387.             {
  388.             bright = (int)(0x5f* ((*p))*invmax) + 0x10;    
  389.             cpack ( (rc+bright&0xff) |
  390.             (((gc+bright)<<8)&0xff00) |
  391.             (((bc+bright) << 16)&0xff0000));
  392.             }
  393.         else cpack(0x111111);
  394.         }
  395.         if( logfreq) xp = xlogpos[io]; else xp += dx;
  396.         vert[0] = xp; vert[1] = *p*invmax; vert[2] = zp;
  397.         v3f(vert);
  398.         vert[0] = xp; vert[1] = power[id+1][io]*invmax; vert[2] = zp+dz;
  399.         v3f(vert);
  400.         }
  401.         endtmesh();
  402.         zp += dz;
  403.       }
  404.         }
  405.     }
  406.     if (mode & TIMELINES) {
  407.     xp = -1.0;
  408.     dz = -1.0;
  409.     for(io=0;io<ORDER; io++) {
  410.         zp = 0.0;
  411.         if (!mono) {
  412.         rc = (io <= ORD2) ? (0xff*(ORD2-io)/ORDER) : 0;
  413.         gc = (io <= ORD2) ? (0xff*(io)/ORDER) : 0xff*(ORDER-io)/ORDER;
  414.         bc = (io <= ORD2) ? 0 : (0x80*io)/ORDER;
  415.         }
  416.         if( logfreq) xp = xlogpos[io]; else xp += dx;
  417.         bgnline();
  418.         vert[0] = xp; vert[1] = 0.0; vert[2] = 0.0;
  419.         v3f(vert);
  420.         for (id=0;id<DURATION;id++) {
  421.             if (!mono) {
  422.             bright = (int)(0x3f* ((power[id][io]))*invmax) + 0x40;    
  423.             cpack ( (rc+bright&0xff) |
  424.                 (((gc+bright)<<8)&0xff00) |
  425.                 (((bc+bright) << 16)&0xff0000));
  426.         }
  427.         if (tmeshmode) cpack(0x000000);
  428.             vert[0] = xp; vert[1] = power[id][io]*invmax; vert[2] = zp;
  429.             v3f(vert);
  430.         zp += dz;
  431.         }
  432.         endline();
  433.     }
  434.     }
  435.     if (mode & FREQLINES) {
  436.     dz = 1.0;
  437.     zp = -DURATION+dz;
  438.     cpack(0xffffff);
  439.     for(id=DURATION-1;id>=0; id--) {
  440.         xp = -1.0;
  441.         p = &power[id][0];
  442.         bgnline();
  443.         vert[0] = 0.0; vert[1] = ((*p))*invmax; vert[2] = zp;
  444.         v3f(vert);
  445.         for (io=0;io<ORDER;io++,p++) {
  446.         if (!mono) {
  447.             if (io <= ORD2)
  448.             {
  449.             rc =  0xff*(ORD2-io)/ORDER;
  450.             gc = 0xff*(io)/ORDER;
  451.             bc = 0;}
  452.             else
  453.             {
  454.             rc = 0;
  455.             gc = 0xff*(ORDER-io)/ORDER;
  456.             bc = (0x80*io)/ORDER;
  457.             }
  458.  
  459.         bright = (int)(0x3f* ((*p))*invmax) + 0x40;    
  460.         cpack ( (rc+bright&0xff) |
  461.             (((gc+bright)<<8)&0xff00) |
  462.             (((bc+bright) << 16)&0xff0000));
  463.         }
  464.         if (tmeshmode) cpack(0x000000);
  465.         if( logfreq) xp = xlogpos[io]; else xp += dx;
  466.             vert[0] = xp; vert[1] = power[id][io]*invmax; 
  467.             v3f(vert);
  468.         }
  469.         endline();
  470.         zp += dz;
  471.     }
  472.     }
  473.     if (mode & AMPLINES) {
  474.     xp = -1.0;
  475.     dz = -1.0;
  476.     for(io=0;io<ORDER; io++) {
  477.         zp = 0.0;
  478.         if (!mono) {
  479.         rc = (io <= ORD2) ? (0xff*(ORD2-io)/ORDER) : 0;
  480.         gc = (io <= ORD2) ? (0xff*(io)/ORDER) : 0xff*(ORDER-io)/ORDER;
  481.         bc = (io <= ORD2) ? 0 :  (0x80*io)/ORDER;
  482.         }
  483.         if (logfreq) xp = xlogpos[io]; else xp += dx;
  484.         for (id=0;id<DURATION;id++) {
  485.             if (!mono) {
  486.             bright = (int)(0x3f* ((power[id][io]))*invmax) + 0x40;    
  487.             cpack ( (rc+bright&0xff) |
  488.                 (((gc+bright)<<8)&0xff00) |
  489.                 (((bc+bright) << 16)&0xff0000));
  490.         }
  491.         if (tmeshmode) cpack(0x000000);
  492.         bgnline();
  493.         vert[0]= xp; vert[1] = 0.0; vert[2] = zp;
  494.         v3f(vert);
  495.         vert[1] = power[id][io]*invmax; 
  496.         v3f(vert);
  497.         endline();
  498.         zp += dz;
  499.         }
  500.     }
  501.     }
  502.  
  503. }
  504.  
  505.  
  506. static void    drawaxis()
  507. {
  508.     move(0.0, 0.0, 0.0);
  509.     cpack(0xff);
  510.     draw(ORDER, 0.0, 0.0);
  511.     move(0.0, 0.0, 0.0);
  512.     cpack(0xff00);
  513.     draw(0.0,.50, 0.0);
  514.     move(0.0, 0.0, 0.0);
  515.     cpack(0xff0000);
  516.     draw(0.0, 0.0, -DURATION);
  517. }
  518.  
  519. static void    initialize(void)
  520. {
  521.     int i;
  522.     float xscale ;
  523.     /* Initialsize xlogpos table */
  524.     curfftsize = BUFCHUNKSIZE;
  525.     tmeshmode = 0;
  526.     logfreq = 0;
  527.     xscale = ORDER*1.0 / flog(ORDER*1.0);
  528.     for (i=0;i<ORDER;i++)
  529.     xlogpos[i] = flog( (i+1)*1.0) * xscale;
  530.     gid = winopen("Visual Audio");
  531.  
  532.     if (DB) doublebuffer();
  533.     if(getgdesc(GD_BITS_NORM_SNG_RED) == 0) candoRGB = 0;
  534.     else candoRGB = 1;
  535.     if (!candoRGB) { fprintf(stderr, " Amesh requires RGB mode to run \n"); exit(1);}
  536.     RGBmode();
  537.     shademodel( GOURAUD);
  538.     zbuffer(zbuf);
  539.     gconfig();
  540.     RGBcolor(0, 0, 0);
  541.     clear();
  542.     if(DB)  { swapbuffers(); clear(); }  else gsync();
  543.     if (zbuf) zclear();
  544.     qdevice(INPUTCHANGE);
  545.     qdevice(REDRAW);
  546.     qdevice(ESCKEY);
  547.     qdevice(WINQUIT);
  548.     qdevice(WINSHUT);
  549.     qdevice(WINFREEZE);
  550.     qdevice(WINTHAW);
  551.     qdevice(LEFTMOUSE);
  552.     qdevice(MIDDLEMOUSE);
  553.     qdevice(RIGHTMOUSE);
  554.     qdevice(RKEY);            /* replay current sample */
  555.     qdevice(LEFTARROWKEY);        /* following four move wheel */
  556.     qdevice(RIGHTARROWKEY);
  557.     qdevice(UPARROWKEY);
  558.     qdevice(DOWNARROWKEY);
  559.     qdevice(BKEY);            /* Toggle wheel on/off */
  560.     qdevice(VKEY);            /* Toggle view from/of wheel */
  561.     qdevice(SKEY);            /* Resynchronize without popup menu */
  562.  
  563.     p1[ 0] = p1[ 1] = p1[ 2] = p2[ 0] = p2[ 1]= p2[2] = v1[ 0] = v1[ 1] =
  564.         v1[ 2] = v2[ 0] = v2[ 1]= v2[ 2] = 0.0;
  565.     facingz = -DURATION/2+3;
  566.     generate();
  567.     dist = DURATION  + 70.0;
  568.  
  569.     perspective(500, 5.0/4.0, 0, dist);
  570.  
  571.     qreset();
  572.     qenter(REDRAW, (short)winget());
  573. }
  574.  
  575. /* extern "C" ALerrfunc ALseterrorhandler(ALerrfunc efunc); /*XXXX*/
  576.  
  577. static void efunc( long num, const char * ch, ...)
  578. {
  579. }
  580.  
  581. /* func is given by logical or of FIRSTTIME, OUTPORT, and INPORT */
  582. static void    open_audio(short func)
  583. {
  584.     ALerrfunc    origfunc;
  585.     short        badopen = 0;
  586.  
  587.     origfunc = ALseterrorhandler(efunc);
  588.     if (func & FIRSTTIME) {
  589.         conf = ALnewconfig();
  590.         ALsetwidth(conf, AL_SAMPLE_16);
  591.         ALsetchannels(conf, AL_MONO);
  592.         port = 0;
  593.     }
  594.     if (func & INPORT) badopen = badopen ||
  595.         ((port = ALopenport("audio_in", "r", conf)) == 0);
  596.     if (badopen) {
  597.         fprintf(stderr, "%s: could not open the necessary audio ports\n",
  598.         myname);
  599.         system("inform 'could not open the audio ports'");
  600.         exit(1);
  601.     }
  602.     ALseterrorhandler(origfunc);
  603. }
  604. /* func is given by a logical or of OUTPORT and INPORT */
  605. static void    close_audio(short func)
  606. {
  607.     if ((func & INPORT) && port) { ALcloseport(port); port = 0; }
  608. }
  609.  
  610.  
  611.  
  612.  
  613. static void    remake_lmenu(void)
  614. {
  615.     long i;
  616.  
  617.     freepup(linemenu);
  618.     linemenu = defpup("Line Widths %t| One %x11| Two %x12| Four %x14| Six %x16");
  619.     for (i = 0; i < 4; i++)
  620.         setpup(linemenu, i+1, PUP_BOX);
  621.     switch (curlinewidth) {
  622.         case 1: i = 1; break;
  623.         case 2: i = 2; break;
  624.         case 4: i = 3; break;
  625.         case 6: i = 4; break;
  626.         default: curlinewidth = 1; i = 1; break;
  627.     }
  628.     setpup(linemenu, i, PUP_CHECK);
  629. }
  630.  
  631. static void    remake_fftmenu(void)
  632. {
  633.     long i;
  634.     long buf [4] ;
  635.     char menustr[400];
  636.     char tmpstr[40];
  637.     long inputfreq;
  638.     float nyquistfreq;
  639.     buf[0] = AL_INPUT_RATE;
  640.     ALgetparams (AL_DEFAULT_DEVICE,buf,2);
  641.     inputfreq = buf[1];
  642.     freepup(fftmenu);
  643.     menustr[0] = '\0';
  644.     strcat(menustr, "FFT Size %t |  128  (0 to");
  645.  
  646.     nyquistfreq = 1.0*inputfreq*ORDER/128/1000;
  647.     sprintf(tmpstr,"%5.1f KHz)", nyquistfreq);
  648.     strcat(menustr,tmpstr);
  649.     strcat(menustr," %x41|  256 (0 to");
  650.  
  651.     nyquistfreq = 1.0*inputfreq*ORDER/256/1000;
  652.     sprintf(tmpstr,"%5.1f KHz)", nyquistfreq);
  653.     strcat(menustr,tmpstr);
  654.     strcat(menustr," %x42|  512 (0 to");
  655.  
  656.     nyquistfreq = 1.0*inputfreq*ORDER/512/1000;
  657.     sprintf(tmpstr,"%5.1f KHz)", nyquistfreq);
  658.     strcat(menustr,tmpstr);
  659.     strcat(menustr," %x43| 1024 (0 to");
  660.  
  661.     nyquistfreq = 1.0*inputfreq*ORDER/1024/1000;
  662.     sprintf(tmpstr,"%5.1f KHz)", nyquistfreq);
  663.     strcat(menustr,tmpstr);
  664.     strcat(menustr," %x44");
  665.  
  666. /*    fftmenu = defpup("FFT Size %t| 128 %x41| 256 %x42| 512 %x43| 1024 %x44"); */
  667.     fftmenu = defpup(menustr); 
  668.     for (i = 0; i < 4; i++)
  669.         setpup(fftmenu, i+1, PUP_BOX);
  670.     switch (curfftsize) {
  671.         case 128: i = 1; break;
  672.         case 256: i = 2; break;
  673.         case 512: i = 3; break;
  674.         case 1024: i = 4; break;
  675.         default: curfftsize = 128; i = 1; break;
  676.     }
  677.     setpup(fftmenu, i, PUP_CHECK);
  678. }
  679. static void    remake_dmenu(void)
  680. {
  681.     long i;
  682.  
  683.     freepup(drawmenu);
  684.     drawmenu = defpup("Draw modes %t|Draw Time %x8|Draw Frequency %x9|Draw Amplitude %x10");
  685.     for (i = 0; i < 3; i++)
  686.         setpup(drawmenu, i+1, (mode & (TIMELINES << i)) ?
  687.         PUP_CHECK : PUP_BOX);
  688. }
  689.  
  690. static void    remake_wmenu(void)
  691. {
  692.     freepup(wheelmenu);
  693.     wheelmenu = defpup("Wheel Options %t|Wheel %x5|Wheel View %x6");
  694.     setpup(wheelmenu, 1, buggy ? PUP_CHECK : PUP_BOX);
  695.     setpup(wheelmenu, 2, buggyview ? PUP_CHECK : PUP_BOX);
  696. }
  697.  
  698.  
  699. static void    remake_mmenu(void)
  700. {
  701.     if (mono) setpup(mainmenu, 3, PUP_BOX);
  702.     else setpup(mainmenu, 3, PUP_CHECK);
  703.     
  704.     if (logfreq) setpup(mainmenu, 4, PUP_CHECK);
  705.     else setpup(mainmenu, 4, PUP_BOX);
  706.     if (tmeshmode) setpup(mainmenu, 5, PUP_CHECK);
  707.     else setpup(mainmenu, 5, PUP_BOX);
  708.  
  709. }
  710.  
  711. static void    remake_menus(void)
  712. {
  713.     freepup(mainmenu);
  714.     mainmenu = defpup("Visual Audio %t|Draw Modes %x0%m|Line Width %x0%m|Color %x2|Log Freq Scale %x30|Tmesh %x32|Wheel %x0%m|FFT Size %x40%m|Quit %x1", drawmenu, linemenu,  wheelmenu, fftmenu);
  715.     remake_mmenu();
  716.     remake_fftmenu();
  717.     }
  718.  
  719. static void    make_menus(void)
  720. {
  721.     remake_lmenu();
  722.     remake_wmenu();
  723.     remake_dmenu();
  724.     remake_fftmenu();
  725.     remake_menus();
  726. }
  727.  
  728. static int    wait_till_thawed(void)
  729. {
  730.     long    dev;
  731.     short    val;
  732.  
  733.         close_audio(INPORT | OUTPORT);
  734.     do {
  735.         dev = qread(&val);
  736.     } while (dev != WINQUIT && dev != WINSHUT && dev != WINTHAW);
  737.     if (dev == WINQUIT || dev == WINSHUT) return TRUE;
  738.     open_audio(INPORT | OUTPORT);
  739.     qenter(REDRAW, (short)winget());
  740.     return FALSE;
  741. }
  742.  
  743. static void    usage(void)
  744. {
  745.     fprintf(stderr,"usage: %s  \n",myname);
  746.     system("inform 'usage: amesh  '");
  747.     exit(1);
  748. }
  749.  
  750.  
  751. void main( int argc, char **argv) 
  752. {
  753.     long    xrot,yrot,zrot;
  754.     long    i, ntoread, dev;
  755.     int        nframe=0;
  756.     short    done = FALSE, stowed = FALSE, val;
  757.     long    nfilled;
  758.     
  759.     float    time_per_frame = 0.0, timefact = 1.0, basetime = 0.0;
  760.  
  761.  
  762.     for (i=0;i<8000;i++) tbuf[i] = (SAMPLE) ( (i*8)%256 - 128 );
  763.     xrot = yrot = zrot = 0;
  764.     dotmesh = 0;
  765.  
  766.  
  767.     open_audio(FIRSTTIME | INPORT /* | OUTPORT */);
  768.  
  769.     initialize();
  770.  
  771.     idur = 0;
  772.  
  773.     /* if (port) ALsetfillpoint(port, (ALgetqueuesize(conf) - BUFCHUNKSIZE)); */
  774.   
  775.     playmode = 1;
  776.     mode = FREQLINES;
  777.     prevmode = mode;
  778.     make_menus();
  779.  
  780.  
  781.  
  782.     while (!done) {
  783.     draw_scene();
  784.     idur++;
  785.     if (idur >= MAXDURATION) idur = 0;
  786.  
  787.     
  788.     nfilled = ALgetfilled(port);
  789.     ntoread = nfilled > ABUFFERSIZE ? ABUFFERSIZE : nfilled;
  790.     
  791.  
  792.     ALreadsamps(port, (void *) tbuf, ntoread);
  793.         pwr = spectrum(tbuf+(ntoread-curfftsize), 
  794.             curfftsize, &[idur][0], ORDER, 0.0 );
  795.     if (pwr < maxpwr) nframe++;
  796.     if (nframe > DURATION) { nframe = 0; maxpwr *= 0.97;}
  797.     if (pwr > maxpwr) { maxpwr = pwr; nframe = 0 ;}
  798.  
  799.     timefact = 1.0;
  800.  
  801.         /* Thant's input code */
  802.     while(qtest() /*  || (!function && low_tmp<2) */ ) {
  803.         dev=qread(&val);
  804.         switch(dev) {
  805.         case INPUTCHANGE:
  806.             active = val;
  807.             break;
  808.         case WINQUIT:
  809.         case WINSHUT: done = TRUE; break;
  810.         case WINFREEZE: stowed = TRUE; break;
  811.         case ESCKEY :
  812.             if (!val) done = TRUE;
  813.             break;
  814.         case SKEY:
  815.             break;
  816.         case VKEY:
  817.             if (( val == 0) || (!buggy)    ) break;
  818.             buggyview = !buggyview;
  819.             break;
  820.         case LEFTMOUSE:
  821.             mx = (short) getvaluator(MOUSEX);
  822.             my = (short) getvaluator(MOUSEY);
  823.             timefact *= LMTIMEFACT;
  824.             if (val) {
  825.             function=REDISTANCE;
  826.             setvaluator(MOUSEX, mx,(short) origx+1,
  827.                 (short)(origx+sizex-1));
  828.             setvaluator(MOUSEY, my,(short) origy+1,
  829.                 (short)(origy+sizey-1));
  830.             omx = mx; omy = my;
  831.             } else {
  832.             function=0;
  833.             setvaluator(MOUSEX, mx, 0, XMAXSCREEN);
  834.             setvaluator(MOUSEY, my, 0, YMAXSCREEN);
  835.             dist += d_dist; d_dist = 0.0;
  836.             }
  837.             break;
  838.         case MIDDLEMOUSE:
  839.             timefact *= MMTIMEFACT;
  840.             mx = (short)getvaluator(MOUSEX);
  841.             my = (short)getvaluator(MOUSEY);
  842.             if (val) {
  843.             function=REORIENT;
  844.             setvaluator(MOUSEX, mx, (short)origx+1,
  845.                 (short)(origx+sizex-1));
  846.             setvaluator(MOUSEY, my, (short)origy+1,
  847.                 (short)(origy+sizey-1));
  848.             omx = mx; omy = my;
  849.             } else {
  850.             function=0;
  851.             setvaluator(MOUSEX, mx, 0, XMAXSCREEN);
  852.             setvaluator(MOUSEY, my, 0, YMAXSCREEN);
  853.             azim += d_azim; d_azim = 0;
  854.             inc += d_inc; d_inc = 0;
  855.             }
  856.             break;
  857.         case RIGHTMOUSE:
  858.             if (val) {
  859.             long menval;
  860.             /* in case the input rate has changed */
  861.             remake_fftmenu(); 
  862.             menval = dopup(mainmenu);
  863.             switch (menval) {
  864.                 case -1: break;
  865.                 case 1: /* quit */
  866.                 done = 1;
  867.                 break;
  868.                 case 2: /* color */
  869.                 mono ^= 1;
  870.                 remake_mmenu();
  871.                 break;
  872.                 case 5: /* wheel toggle */
  873.                 buggy ^= 1;
  874.                 remake_wmenu();
  875.                 remake_menus();
  876.                 break;
  877.                 case 6: /* wheel view toggle */
  878.                 buggyview ^= 1;
  879.                 remake_wmenu();
  880.                 remake_menus();
  881.                 break;
  882.                 case 8: /* toggle time */
  883.                 mode ^= TIMELINES;
  884.                 goto fix_time_per_frame;
  885.                 case 9: /* toggle frequency */
  886.                 mode ^= FREQLINES;
  887.                 goto fix_time_per_frame;
  888.                 case 10: /* toggle amplitude */
  889.                 mode ^= AMPLINES;
  890.                 fix_time_per_frame:
  891.                 remake_dmenu();    /* also fixup menu    */
  892.                 remake_menus();
  893.                 /* nothing yet */
  894.                 break;
  895.                 case 11: case 12: case 13: case 14:
  896.                 case 15: case 16: case 17: case 18: case 19:
  897.                 curlinewidth = (int)(menval-10);
  898.                 remake_lmenu();
  899.                 remake_menus();
  900.                 break;
  901.                 case 21:
  902.                 case 22:
  903.                 case 30: /* logfreq */
  904.                 logfreq ^= 1;
  905.                 remake_mmenu();
  906.                 break;
  907.                 case 32: /* Tmesh */
  908.                 if (tmeshmode) {tmeshmode=0;  mode=prevmode; }
  909.                 else { 
  910.                     prevmode = mode; tmeshmode = 1; 
  911.                     mode = 0;  mono =0;
  912.                 }
  913.                 remake_mmenu();
  914.                 remake_dmenu();
  915.                 break;
  916.                 case 41: 
  917.                 curfftsize = 128;
  918.                 remake_fftmenu();
  919.                 break;
  920.                 case 42: 
  921.                 curfftsize = 256;
  922.                 remake_fftmenu();
  923.                 break;
  924.                 case 43: 
  925.                 curfftsize = 512;
  926.                 remake_fftmenu();
  927.                 break;
  928.                 case 44: 
  929.                 curfftsize = 1024;
  930.                 remake_fftmenu();
  931.                 break;
  932.                 default:
  933.                 break;
  934.             }
  935.             }
  936.             break;
  937.         case REDRAW:
  938.             reshapeviewport();
  939.             getorigin(&origx, &origy);
  940.             getsize(&sizex, &sizey);
  941.             break;
  942.         case LEFTARROWKEY:
  943.             if ( val == 0) break;
  944.             facing += 1;
  945.             if ( facing + ORDER/2 >= ORDER) facing = -ORDER/2;
  946.             break;
  947.         case RIGHTARROWKEY:
  948.             if ( val == 0) break;
  949.             facing -= 1;
  950.             if ( facing + ORDER/2 < 0) facing = ORDER/2 - 1;
  951.             break;
  952.         case UPARROWKEY:
  953.             if ( val == 0) break;
  954.             facingz += 1;
  955.             if ( -DURATION/2 + facingz > 0) facingz = -DURATION/2 + 1;
  956.             break;
  957.         case DOWNARROWKEY:
  958.             if ( val == 0) break;
  959.             facingz -= 1;
  960.             if ( -DURATION/2 + facingz <= -DURATION) facingz = DURATION/2 ;
  961.             break;
  962.         case BKEY:
  963.             if ( val == 0) break;
  964.             buggy = !buggy;
  965.             break;
  966.         }
  967.     }
  968.  
  969.     switch(function) {
  970.  
  971.         case REORIENT:
  972.         mx = (short)getvaluator(MOUSEX);
  973.         my = (short)getvaluator(MOUSEY);
  974.         d_azim = (short)((omx - mx) * 2 * XMAXSCREEN / sizex);
  975.         d_inc = (short)((my - omy) * 2 * YMAXSCREEN / sizey);
  976.         break;
  977.  
  978.         case REDISTANCE:
  979.         mx = (short)getvaluator(MOUSEX);
  980.         my = (short)getvaluator(MOUSEY);
  981.         d_dist = ((omx - mx) + (my - omy)) * XMAXSCREEN /sizex;
  982.         break;
  983.     }
  984.  
  985.  
  986.     if (stowed) {
  987.         done = wait_till_thawed();
  988.         stowed = FALSE;
  989.     }
  990.  
  991.     }
  992.     close_audio(INPORT /* | OUTPORT */);
  993. }
  994.  
  995.